package puppy.eval;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;

import java.util.Hashtable;

import java.util.Map.Entry;

import algorithms.Constants;
import algorithms.PageRankSuggestions;
import algorithms.models.FeatureBag;
import algorithms.models.QueryTagsModel;
import algorithms.models.QueryTopicsModel;

import fileloaders.extractors.AOLQueryPairsExtractor;
import fileloaders.extractors.LineFieldExtractor;
import fileloaders.extractors.YahooQueryPairsExtractor;
import fileloaders.filters.AOLQueryPairFilter;
import fileloaders.filters.TextLineFilter;
import fileloaders.filters.YahooQueryPairFilter;

import puppy.eval.logloaders.QueryPairsLoader;
import puppy.graph.DeliciousNode;
import puppy.graph.DeliciousNodeTransformer;


import util.evaluation.StatsGenerator;
import util.io.FileOutput;

import util.ranker.RankingService;

public class EvaluateSuggestions {

	//AgeGroupAggregator agg=null;

	private Hashtable<String,Hashtable<String, ArrayList<String>>> gold = new Hashtable<String,Hashtable<String, ArrayList<String>>>();
	
	private	StatsGenerator stats = null;
	private QueryPairsLoader loader = null;
	private TextLineFilter filter =null;
	private LineFieldExtractor extractor=null;

	//FileOutput out=null;

	private boolean featuresUpdate=false;
	public EvaluateSuggestions(String path_logs, String logs_type, HashSet<String> valid_ages, boolean onlyClicks, int duration, boolean onlyManual, String output_path){
		
		if(logs_type.equals("aol")){
			filter = new AOLQueryPairFilter(valid_ages,onlyClicks,duration);
			extractor = new AOLQueryPairsExtractor();
			
		}else {
			filter = new YahooQueryPairFilter(valid_ages,onlyClicks,duration, onlyManual);
			extractor = new YahooQueryPairsExtractor();
			
		}
		
		loader = new QueryPairsLoader(path_logs, filter,extractor);
		
	
		
		/*if(output_path!=null){
			
			out= new FileOutput(output_path);
		}
		*/
		gold = loader.loadQueryPairs();
		
		stats = new StatsGenerator(gold,null);

	}

	public Hashtable<String, ArrayList<String>> rankQueries(RankingService service, int limit) {

		Enumeration<String> types = gold.keys();
		Hashtable<String, ArrayList<String>> suggs = new Hashtable<String, ArrayList<String>>();
		 StringBuffer buffer = new StringBuffer("");
		while(types.hasMoreElements()){
			Hashtable<String, ArrayList<String>> temporal = gold.get(types.nextElement());	
			Enumeration<String> queries = temporal.keys();
			
			while(queries.hasMoreElements()){
				
				String query  = queries.nextElement();
				if(suggs.containsKey(query)){
					
					continue;
				}
				
				ArrayList<Entry<String, Float>> ranked = service.rankQuery(query,limit);
				
				PageRankSuggestions service_pg=null;
				
				if(featuresUpdate){
					
					service_pg = (PageRankSuggestions)service;
					
					Hashtable<String, FeatureBag> bag = service_pg.features;
					String temp= createQueryFeatures( query, bag).toString();
					//System.out.println(temp);
					
					
				//	buffer.append(createQueryFeatures( query, bag));
					
				}
				
				
				int rank = 1;
				int index=0;
					// printing ranked suggestions for query
					while (ranked != null && index < ranked.size()) {

						Entry<String, Float> suggestion = ranked.get(index);
						index++;
						
						String suggested = suggestion.getKey();
						suggested= suggested.replace("_", " ");
						
						updateSuggestionHash(suggs, query, suggested);
						
						
						String temp = query + "\t" + suggested + "\t"
								+ rank + "\n";
					
						// System.out.println(query + "\t" + suggestion.getKey()+
						// "\t" + rank);
						rank++;
					}
			
			
		}
	
		
	}
		
		//updateFile(buffer.toString());
		return suggs;
	}
	
	
	
	
	
	
	private StringBuffer getFeaturesAggregate(String query,
			Hashtable<String, FeatureBag> features) {
		// TODO Auto-generated method stub
		
		StringBuffer b= new StringBuffer();
		
		Enumeration<String> tags = features.keys();
		while(tags.hasMoreElements()){
			String tag= tags.nextElement();
			
			FeatureBag f = features.get(tag);
			
			
			
			/**
			 * format 
			 * 
			 * query  tag  rw rank_pos  
			 */
			
		//	System.out.println();
			
		}
		
		return null;
	}

	public Hashtable<String, ArrayList<String>> rankQueries(RankingService service, QueryTagsModel model, int limit) {

		Enumeration<String> types = gold.keys();
		Hashtable<String, ArrayList<String>> suggs = new Hashtable<String, ArrayList<String>>();
		StringBuffer buffer= new StringBuffer("");
		while(types.hasMoreElements()){
			Hashtable<String, ArrayList<String>> temporal = gold.get(types.nextElement());	
			Enumeration<String> queries = temporal.keys();
			
			while(queries.hasMoreElements()){
				
				String query  = queries.nextElement();
			
				if(suggs.containsKey(query)){
					
					continue;
				}
				
				Hashtable<String,Float> q= null;
				ArrayList<Entry<String, Float>> ranked=null;
				
				if(model!=null && model.getQueryHash() !=null && model.getQueryHash().containsKey(query)){
					
					
					q = model.getQueryHash().get(query);
					ranked = service.rankQuery(query,q,limit);
				}
				else{
					
				ranked = service.rankQuery(query,limit);
				}
				
				int rank = 1;
				int index=0;
				PageRankSuggestions service_pg=null;
				
				if(featuresUpdate){
					
					service_pg = (PageRankSuggestions)service;
					
					Hashtable<String, FeatureBag> bag = service_pg.features;
					buffer.append(createQueryFeatures( query, bag));
					
				}
					// printing ranked suggestions for query
					while (ranked != null && index < ranked.size()) {

						Entry<String, Float> suggestion = ranked.get(index);
						index++;
						String suggested = suggestion.getKey();
						suggested= suggested.replace("_", " ");
						
						updateSuggestionHash(suggs, query, suggested);
						//System.out.println("aqui");
						
						String temp = query + "\t" + suggested + "\t"
								+ rank + "\n";

						 
					//	buffer.append(query + "\t" + suggestion.getKey()+ "\t" +suggestion.getValue() + "\t" + rank + "\n");
						 
					if(Constants.debug){	 
						 System.out.println(query + "\t" + suggestion.getKey()+
						 "\t" + rank);
						 
					}
						rank++;
					}
			
			
		}
	
		
	}
	//	updateFile(buffer.toString());
		return suggs;
	}
	
	
	
	public Hashtable<String, ArrayList<String>> rankQueries(RankingService service, QueryTagsModel model, QueryTopicsModel q_topics, int limit) {

		Enumeration<String> types = gold.keys();
		Hashtable<String, ArrayList<String>> suggs = new Hashtable<String, ArrayList<String>>();
	
		
		StringBuffer buffer= new StringBuffer("");
		while(types.hasMoreElements()){
			Hashtable<String, ArrayList<String>> temporal = gold.get(types.nextElement());	
			Enumeration<String> queries = temporal.keys();
			
			while(queries.hasMoreElements()){
				
				String query  = queries.nextElement();
		
				if(suggs.containsKey(query)){
					
					continue;
				}
				
				Hashtable<String,Float> q= null;
				Hashtable<String,Float> topics= null;
				
				ArrayList<Entry<String, Float>> ranked=null;
				
				if(model!=null && model.getQueryHash() !=null && model.getQueryHash().containsKey(query)){
				
					
					q = model.getQueryHash().get(query);
					
					
					if(q_topics!=null && q_topics.q_topics!=null){
						
						topics = q_topics.q_topics.get(query);
						//System.out.println(query + "\t not found in topics model");
						//System.exit(1);
						
					}
					
					ranked = service.rankQuery(query,q, topics,limit);
				}
				else{
					
				ranked = service.rankQuery(query,limit);
				}
				
				PageRankSuggestions service_pg=null;
				
				if(featuresUpdate){
					
					service_pg = (PageRankSuggestions)service;
					
					Hashtable<String, FeatureBag> bag = service_pg.features;
				//	buffer.append(createQueryFeatures( query, bag));
					System.out.println(createQueryFeatures( query, bag));
					
				}
				
				int rank = 1;
				int index=0;
					// printing ranked suggestions for query
					while (ranked != null && index < ranked.size()) {

						Entry<String, Float> suggestion = ranked.get(index);
						index++;
						String suggested = suggestion.getKey();
						suggested= suggested.replace("_", " ");
						
						
						
						updateSuggestionHash(suggs, query, suggested);
						//System.out.println("aqui");
						
						String temp = query + "\t" + suggested + "\t"
								+ rank + "\n";
						
						 //System.out.println(query + "\t" + suggestion.getKey()+ "\t" + rank);
						
						 
						
						rank++;
					}
			
			
		}
	
		
	}
		if(featuresUpdate){
			
		//updateFile(buffer.toString());
		buffer=null;
		
		}
		return suggs;
	}
	
	
	
	
	/**
	 * format   query suggestion rw rank p(kids) p(adults) kl  p(query)
	 * 
	 * @param bag
	 * @return
	 */
	private StringBuffer createQueryFeatures(String query,Hashtable<String,FeatureBag> bag){
		
		StringBuffer buffer =new StringBuffer("");
		
		Enumeration<String> suggestions = bag.keys();
		while(suggestions.hasMoreElements()){
			
			String suggestion= suggestions.nextElement();
			FeatureBag b = bag.get(suggestion);
			buffer.append(query+"\t");
			buffer.append(suggestion+"\t");
			buffer.append(b.score + "\t");
			buffer.append(b.rank+ "\t");
			buffer.append(b.prob_kids+ "\t");
			buffer.append(b.prob_adults+ "\t");
			buffer.append(b.kl+ "\t");
			buffer.append(b.q_lm+ "\t");
			
			/*
			 * extract matching 
			 * 
			 */
			int k=0;
			HashSet<String> approx = stats.searchApproxMatches(query, suggestion);
			HashSet<String> exact = stats.searchExactMatches(query, suggestion);
			
			int ap=0;
			if(approx.size()>0){
				ap=1;
			}		
			
			int ex=0;
			if(exact.size()>0){
				ex=1;
			}	
			
			
			buffer.append(ap+ "\t");
			buffer.append(ex+ "\n");
		}
		return buffer;
	}
		
	/*private void updateFile( String string) {
		// TODO Auto-generated method stub
		
		
		if(out==null)return;
		
		out.createFile(output_path, string);
		
	}
*/
	private void updateSuggestionHash(
			Hashtable<String, ArrayList<String>> suggs,
			String query, String suggested) {
		// TODO Auto-generated method stub
		
		 ArrayList<String>temp = new ArrayList<String>();
		
		if(suggs.containsKey(query)){
			
			temp = suggs.get(query);
			
		}
	  suggs.put(query, temp);
	  temp.add(suggested);
	}

	
	public void performEvaluation(RankingService service, QueryTagsModel model) throws IOException{
		//System.out.println(" model byut not topics");
		//System.exit(1);
		Hashtable<String, ArrayList<String>> suggestions =rankQueries(service,model, 100);
		
		stats.evaluate(suggestions);
	}
	
	public void performEvaluation(RankingService service, QueryTagsModel model, QueryTopicsModel q_topics) throws IOException{
	
	
		Hashtable<String, ArrayList<String>> suggestions =rankQueries(service,model, q_topics,100);
	
		
		stats.evaluate(suggestions);
	}
	
	
	public void performEvaluation(RankingService service) throws IOException{
		//System.out.println(" no topics no models using topics");
	//	System.exit(1);
		Hashtable<String, ArrayList<String>> suggestions =rankQueries(service, 100);
		
	
		stats.evaluate(suggestions);
	}
	
	
	public Hashtable<String,Hashtable<String, ArrayList<String>>> getGoldStandard(){
		
		return gold;
	}
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

	
		
		String prefix_data="/Users/sergioduarte/projects/data/";
	//	prefix_data= "/home/sergio/data/";

		String evaluation_path = prefix_data + "results/aol_query_reformulations/all_long_click_kids.txt";
		//evaluation_path=prefix_data + "query_suggestions/sample.txt";
		
		String in_path = prefix_data+ "results/query_and_tags_sorted_aol/query_and_tags_sorted_aol.txt";
		
		String path= prefix_data + "results/query_suggestions_google";
	
		//evaluation_path=args[0];
		//path= args[1];
//
	//	EvaluateSuggestionsAOL eval = new  EvaluateSuggestionsAOL(evaluation_path);
		
		
		//eval.initAggregator(y_4_5, y_6_7, y_8_9, y_10_12, y_13_15, y_16_18, y_19_25, adults);

	//	SuggestionsFromFile sugges= new SuggestionsFromFile(path);
		//PageRankSuggestions page = new PageRankSuggestions(pat;h);
	
		//page.initAggregator(true, true, true, true, false, false, false);
		//page.performPageRankWithPriors();
	//	eval.performEvaluation(sugges);
	}

	
	
}
